Add trade confirmation parsing and transaction fees processing#188
Draft
mbronk wants to merge 5 commits intoRustInFinance:mainfrom
Draft
Add trade confirmation parsing and transaction fees processing#188mbronk wants to merge 5 commits intoRustInFinance:mainfrom
trade confirmation parsing and transaction fees processing#188mbronk wants to merge 5 commits intoRustInFinance:mainfrom
Conversation
Polish tax law requires different rounding methods depending on income type,
which was not previously implemented. This change brings the calculation into
compliance with Art. 63 Ordynacji Podatkowej (OP).
1. Per currency-converted "tax event" (i.e. stock sales, dividend...),
convert each result to full "grosz" (0,01 precision) - before
summing.
Basis: Mathematical rounding rules (0,01zł is the lowest monetary
value)
2. Interests and dividends are separated as they follow different
rounding rules when calculating the lump-sum tax
a) Interests aggregate (art. 30a ust. 1 pkt 3 PIT) as well as
their resulting lump-sum tax, are rounded UP to the nearest
full "grosz" — art. 63 §1a OP
b) Dividends aggregate (art. 30a ust. 1 pkt 4 PIT) as well
as their resulting lump-sum tax, are rounded to the nearest
full ZLOTY (0,50zl -> 1zl) — art. 63 §1 OP
c) Foreign tax withholding: no rounding the standard FX rule
to round to grosz (0,01) precision - rule #1 (above)
d) Net/gross/cost stock proceeds are not subject to lump-sum
tax calculations and reported in full on PIT-38 form, hence
only standard FX rules (#1-above) applies and they are reported
with "grosz" precision.
Signed-off-by: Mateusz Bronk <mbronk@users.noreply.github.com>
Per tax advisor consultation with Naczelna Izba Skarbowa and Art. 63 Ordynacja Podatkowa, rounding should only be applied to final tax base and tax amount sums, not to individual transactions. Change default behavior to carry full f32 precision through per-transaction FX conversions. The previous per-transaction rounding to grosz is preserved as an opt-in flag: - CLI: --round-per-transaction - GUI: Options menu toggle (MenuBar) Also add default-run to Cargo.toml to resolve binary ambiguity. Signed-off-by: Mateusz Bronk <mbronk@users.noreply.github.com>
Signed-off-by: Mateusz Bronk <mbronk@users.noreply.github.com>
Replace all f32/f64 money types with rust_decimal::Decimal for precise financial arithmetic. This eliminates floating-point representation errors in tax computations. Motivation: starting at 131,072 PLN (2^17), f32's ULP reaches 0.015625, exceeding 0.01 PLN and making it impossible to represent individual grosz values correctly. Any realistic portfolio of ~$30k+ in US stock sales converted at ~4 PLN/USD crosses this threshold. A new test (test_decimal_precision_vs_f32_sold_taxation) demonstrates a concrete 1-grosz error on a PIT-38-realistic scenario with just 3 trades. Key changes: - Add rust_decimal 1.36.0 (macros, serde-with-float features) - Convert all money types (Currency, Transaction, SoldTransaction, TaxCalculationResult) and rounding functions to Decimal - Update parsers: PDF uses DecimalEntry; CSV parses &str→Decimal directly; XLSX converts calamine f64→Decimal (IEEE 754 unavoidable) - NBP rates: serde-with-float deserialization, cached rates as dec!() - ECB rates: Decimal division for inverse exchange rates - Round gross_sold/cost_sold to grosz in run_taxation output - Add rust_decimal.natvis for VS debugger visualization - Add proof test for f32 grosz error; update all existing tests Signed-off-by: Mateusz Bronk <mbronk@users.noreply.github.com>
What: Use Trade Confirmation commission/fee data to increase tax cost basis while keeping sale proceeds reported as gross proceeds (separate fields). Why: - Polish PIT-38 capital-gains reporting requires separate values for proceeds (przychod) and deductible costs (koszty uzyskania przychodu). - Booking brokerage fees into costs (instead of blending into proceeds) keeps reconstructed SELL data aligned with tax-form semantics. How: - Parse Trade Confirmation PDFs and extract trade_date, settlement_date, quantity, price, principal, commission, fee, and net amount. - Match confirmations to sold rows using normalized (trade_date, settlement_date, quantity, price, symbol). - Allocate same-day, same-symbol G&L lots to sold rows via quantity-constrained DFS/knapsack matching. - Reconstruct sold transactions by proportional fee allocation per matched row. - Store fees separately and add them into cost basis; keep proceeds and costs as distinct output values. - If confirmation matching remains ambiguous even after price matching, continue with deterministic selection and emit explicit warnings (including principal/net candidate diagnostics) surfaced in CLI and GUI notes. - Strengthen validation and diagnostics to distinguish missing statement entries from quantity/symbol inconsistencies. - Keep integer-only quantity handling from G&L. Signed-off-by: Mateusz Bronk <mbronk@users.noreply.github.com>
45ce7d9 to
7c9941d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Important
Non-standalone! (therefore
DRAFT, until #187 is dispositioned)Separate gross proceeds from costs for PIT-38 sold transactions
What:
Use Trade Confirmation commission/fee data to increase tax cost basis while keeping sale proceeds reported as gross proceeds (separate fields).
Why:
How: